﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Utilities;
using Irony.Parsing;

namespace ScriptIrony
{
   public class GrampAst
   {
      private static Logger logger_ = Program.logger;
      public GrampAst parent;
      public List<GrampAst> children;

      public class SimpleAst
      {
         public ParseTreeNode node;
         public SortedList<int, SimpleAst> children;
         public SimpleAst(ParseTreeNode childNode)
         {
            node = childNode;
         }
      }

      public class Ast
      {
         public Ast parent;
         public List<Ast> children;
         public ParseTreeNode node;
      }

      public GrampAst(ParseTreeNode node)
      {
         // Copy the parse tree into our own structure so we can manipulate it
         // into an AST without killing Irony
         Ast root = cloneTree(null, node);
      }

      private Ast cloneTree(Ast parent, ParseTreeNode node)
      {
         Ast cloneNode = new Ast();
         cloneNode.node = node;
         cloneNode.parent = parent;
         if ((null != node.ChildNodes) && (0 < node.ChildNodes.Count))
         {
            cloneNode.children = new List<Ast>();
            node.ChildNodes.ForEach(childNode => cloneNode.children.Add(cloneTree(cloneNode, childNode)));
         }
         return cloneNode;
      }

      private void buildAst(SimpleAst thisNode)
      {
         // Does this rule include an AST construct?
         int maxIndex = thisNode.node.ChildNodes.Max(childNode => childNode.Term.astIndex);
         if (0 <= maxIndex)
         {
            // Sort the nodes into astIndex-order. The list will not be very long,
            // so a brute-force approach is OK
            thisNode.children = new SortedList<int, SimpleAst>();
            thisNode.node.ChildNodes.ForEach(childNode =>
               {
                  int effectiveIndex = (0 <= childNode.Term.astIndex) ? childNode.Term.astIndex : ++maxIndex;
                  SimpleAst thisChild = new SimpleAst(childNode);
                  thisNode.children.Add(effectiveIndex, thisChild);
                  buildAst(thisChild);
               });
            return;
         }

         // No AST construct in our children, so 
      }


      //private void climbTree(SimpleNode node)
      //{
      //   try
      //   {
      //      ParseTreeNode tree = node.tree;
      //      int count = ((null != tree) && (null != tree.ChildNodes)) ? tree.ChildNodes.Count : 0;
      //      if (0 == count)
      //      {
      //         // Leaf node, we include it
      //         return;
      //      }
      //      if (1 == count)
      //      {
      //         // There's only one child, so we use that instead
      //         // to eliminate the redundant link
      //         node.tree = tree.ChildNodes[0];
      //         climbTree(node);
      //         return;
      //      }
      //      // More than one child
      //      node.children = new List<SimpleNode>();
      //      tree.ChildNodes.ForEach(childTree =>
      //      {
      //         //if (childTree.ToString() == tree.ToString())
      //         //{
      //         //   // We are doing LR parsing, so it's safe to collapse the left-recursion
      //         //   ParseTreeNode saveTree = node.tree;
      //         //   node.tree = childTree;
      //         //   climbTree(node);
      //         //   tree = saveTree;
      //         //}
      //         //else
      //         {
      //            SimpleNode childNode = new SimpleNode();
      //            childNode.tree = childTree;
      //            node.children.Add(childNode);
      //            climbTree(childNode);
      //         }
      //      });
      //   }
      //   catch (System.Exception ex)
      //   {
      //      logger_.exception(ex);
      //   }
      //}

      //private void dumpTree(SimpleNode node, string indent)
      //{
      //   try
      //   {
      //      if ((null == node.tree.Token) && (null == node.children))
      //      {
      //         // It's a non-terminal that only contained punctuation
      //         return;
      //      }
      //      logger_.debugFormat("{0}{1}", indent.ToString(), node.tree.ToString());
      //      if (null != node.children)
      //      {
      //         node.children.ForEach(child => dumpTree(child, string.Concat(indent, "   ")));
      //      }
      //   }
      //   catch (System.Exception ex)
      //   {
      //      logger_.exception(ex);
      //   }
      //}

      //public void cleanTree(ParseTree tree)
      //{
      //   try
      //   {
      //      SimpleNode node = new SimpleNode();
      //      node.tree = tree.Root;
      //      climbTree(node);

      //      dumpTree(node, string.Empty);
      //   }
      //   catch (System.Exception ex)
      //   {
      //      logger_.exception(ex);
      //   }
      //}
   }
}
